#![cfg_attr(
    all(not(debug_assertions), target_os = "windows"),
    windows_subsystem = "windows"
)]

use std::{path::{Path, PathBuf}, fs::Metadata, time::SystemTime};

use tokio::fs;
use uuid::Uuid;

#[tokio::main]
async fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![file_meta, rename_file])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

#[tauri::command]
async fn rename_file(path: String, old: String, new: String) -> Result<String, String> {
    let mut oldPath = PathBuf::new();
    oldPath.push(&path);
    oldPath.push(&old);
    let mut newPath = PathBuf::new();
    newPath.push(&path);
    newPath.push(&new);
    fs::rename(oldPath, newPath).await;
    println!("old: {}, new: {}", old, new);
    Ok("ok".into())
}

#[tauri::command]
async fn file_meta(path: Vec<String>) -> Result<Vec<FileModel>, String> {
    let mut result = vec![];
    for ele in path {
        let ele_path = Path::new(&ele);
        let ele_clone = ele.clone();
        match fs::metadata(&ele).await {
            Ok(metadata) => {
                result.push(FileModel {id: Uuid::new_v4().to_string(), name: get_file_name(ele_path), ext: get_file_ext(ele_path),
                     path: get_parent_path(ele_path), size: metadata.len(), modified_time: get_modified_time(&metadata)})
            }
            Err(e) => {
                println!("file_metaErr:{:?},Err:{:?}", ele_clone, e);
            }
        }
    }
    Ok(result)
}

fn get_parent_path(path: &Path) -> String {
    match path.parent() {
        Some(p) => {
            String::from(p.to_str().unwrap_or(""))
        },
        None => {
            String::from("")
        },
    }
}

fn get_modified_time(metadata: &Metadata) -> u64 {
    let modified_time = metadata.modified();
    match modified_time {
        Ok(t) => {
            match t.duration_since(SystemTime::UNIX_EPOCH) {
                Ok(n) => n.as_secs(),
                Err(_) => 0,
            }
        },
        Err(_) => {
            0
        },
    }

}

fn get_file_name(path: &Path) -> String {
    match path.file_name() {
        Some(s) => {
            match s.to_str() {
                Some(s1) => {
                    String::from(s1)
                },
                None => {
                    String::from("_")
                },
            }
        },
        None => {
            String::from("_")
        }
    }
}

fn get_file_ext(path: &Path) -> String {
    return match path.extension() {
        Some(s) => {
            match s.to_str() {
                Some(s2) => {
                    String::from(s2)
                },
                None => {
                    String::from("_")
                },
            }
        },
        None => {
            String::from("_")
        },
    };
}

#[derive(Debug, Clone, serde::Serialize)]
struct FileModel {
    id: String,
    name: String,
    ext: String,
    path: String,
    size: u64,
    modified_time: u64

}